package cn.alcode.cardservice.service.impl;

import cn.alcode.cardservice.model.PageRequestParam;
import cn.alcode.cardservice.model.Student;
import cn.alcode.cardservice.service.EcCardService;
import cn.alcode.cardservice.util.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.util.*;

@Slf4j
@Service
public class EcCardServiceImpl implements EcCardService {

    @Value("${ecCard.appId}")
    private String appId;

    @Value("${ecCard.appSecret}")
    private String appSecret;

    @Value("${ecCard.url}")
    private String url;

    private static String METHOD_ADD_ORG = "10";
    private static String METHOD_EDIT_ORG = "11";
    private static String METHOD_DEL_ORG = "12";
    private static String METHOD_ADD_STUDENT = "13";
    private static String METHOD_EDIT_STUDENT = "14";
    private static String METHOD_DEL_STUDENT = "15";
    private static String METHOD_ADD_RECHARGE_RECORD = "16";
    private static String METHOD_QUERY_RECHARGE_RECORD = "17";
    private static String METHOD_QUERY_BALANCE = "18";

    @Override
    public Long doAddOrg(String name, String parentDid) {
        Map<String, String> params = new HashMap<>();

        params.put("dname", name);
        if(StringUtils.isEmpty(parentDid)) {
            parentDid = "10000";
        }
        params.put("dfather", parentDid);

        params.put("dexpiration", "2999-01-01 00:00:00");
        params.put("dnumber", "0");
        params.put("dtel", "");

        String result = HttpUtil.getPostData(url, initParameter(METHOD_ADD_ORG, params));
        JSONObject obj = JSON.parseObject(result);
        if(obj.getInteger("code") == 0) {
            JSONObject resultObj = obj.getJSONObject("result");
            return resultObj.getLong("did");
        }

        return 0L;
    }

    @Override
    public void doUpdateOrg(String name, String did, String parentDid) {
        Map<String, String> params = new HashMap<>();

        params.put("did", did);
        params.put("dname", name);
        if(StringUtils.isEmpty(parentDid)) {
            parentDid = "10000";
        }
        params.put("dfather", parentDid);

        params.put("dexpiration", "2999-01-01 00:00:00");
        params.put("dnumber", "0");
        params.put("dtel", "");

        String result = HttpUtil.getPostData(url, initParameter(METHOD_EDIT_ORG, params));
        log.info(result);
    }

    @Override
    public void doDeleteOrg(String did) {
        Map<String, String> params = new HashMap<>();
        params.put("did", did);
        HttpUtil.getPostData(url, initParameter(METHOD_DEL_ORG, params));
    }

    @Override
    public Long doAddPerson(Student student) {
        Map<String, String> params = new HashMap<>();

        params.put("cnumber", student.getStudentId());
        params.put("cname", student.getName());
        params.put("did", student.getDid().toString());
        params.put("sex", student.getSex());
        params.put("cardid", student.getIdcard());
        params.put("tel", student.getPhoneNumber());
        params.put("post", "1");
        params.put("status", "1");
        params.put("address", "");
        params.put("remark", student.getDescription());
        params.put("bank", "");

        String result = HttpUtil.getPostData(url, initParameter(METHOD_ADD_STUDENT, params));
        JSONObject obj = JSON.parseObject(result);
        if(obj.getInteger("code") == 0) {
            JSONObject resultObj = obj.getJSONObject("result");
            return resultObj.getLong("cid");
        }

        return 0L;
    }

    @Override
    public void doUpdatePerson(Student student) {
        Map<String, String> params = new HashMap<>();

        params.put("cid", student.getCid().toString());
        params.put("cnumber", student.getStudentId());
        params.put("cname", student.getName());
        params.put("did", student.getDid().toString());
        params.put("sex", student.getSex());
        params.put("cardid", student.getIdcard());
        params.put("tel", student.getPhoneNumber());
        params.put("post", "1");
        params.put("status", "1");
        params.put("address", "");
        params.put("remark", student.getDescription());
        params.put("bank", "");

        String result = HttpUtil.getPostData(url, initParameter(METHOD_EDIT_STUDENT, params));
        log.info(result);
    }

    @Override
    public void doDeletePerson(String cid) {
        Map<String, String> params = new HashMap<>();
        params.put("cid", cid);
        HttpUtil.getPostData(url, initParameter(METHOD_DEL_STUDENT, params));
    }

    @Override
    public Integer doAddRechargeRecord(String qcls, String studentCid, String totalAmount, String type, String qdate) {
        Map<String, String> params = new HashMap<>();

        params.put("qcls", qcls);
        params.put("cid", studentCid);
        params.put("category", "1");
        params.put("amount", totalAmount);
        params.put("balance", "");
        params.put("type", type);
        params.put("qdate", qdate);

        String result = HttpUtil.getPostData(url, initParameter(METHOD_ADD_RECHARGE_RECORD, params));
        log.info(result);
        JSONObject obj = JSON.parseObject(result);
        return obj.getInteger("code");
    }

    /**
     * 查询学生交易记录
     * @param page
     * @param studentId
     * @return
     */
    @Override
    public JSONObject queryTransaction(PageRequestParam page, String studentId) {
        Map<String, String> params = new HashMap<>();
        params.put("cnumber", studentId);

        params.put("currPage", page.getPage().toString());
        params.put("pageSize", page.getLimit().toString());

        String result = HttpUtil.getPostData(url, initParameter(METHOD_QUERY_RECHARGE_RECORD, params));
        log.info("cnumber:" + studentId + "result:" + result);
        return JSON.parseObject(result);
    }

    @Override
    public String queryBalance(String cid) {
        Map<String, String> params = new HashMap<>();
        params.put("cid", cid);
        String result = HttpUtil.getPostData(url, initParameter(METHOD_QUERY_BALANCE, params));
        log.info(result);

        JSONObject obj = JSON.parseObject(result);
        if(obj.getInteger("code") == 0) {
            JSONObject objResult = obj.getJSONObject("result");
            return objResult.getString("balance");
        }
        return "0.00";
    }

    <T> List<T> convertJSONArrayToList(JSONArray jsonArray, Class<T> clazz) {
        List<T> resultList = JSON.parseArray(jsonArray.toJSONString(), clazz);
        return resultList;
    }

    Map<String, String> initParameter(String method, Map<String, String> queryParams) {
        Map<String, String> params = new HashMap<>();
        String strQueryParams = JSON.toJSONString(queryParams);
        if(StringUtils.isEmpty(strQueryParams)) {
            strQueryParams = "";
        }

        //data进行Base64编码后再Url编码
        Base64.Encoder base64Encoder = Base64.getEncoder();
        String base64QueryParams = base64Encoder.encodeToString(strQueryParams.getBytes());
//        String urlQueryParams = "";
//        try {
//            urlQueryParams = URLEncoder.encode(base64QueryParams, "UTF-8");
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        }

        String nonce = "15";
//        String nonce = UUID.randomUUID().toString();

        String text = appId + "|" + appSecret + "|" + base64QueryParams + "|" + nonce;
//        String sign = base64Encoder.encodeToString(text.getBytes());

        //MD5加密
        String md5Hash = encodeByMD5(text).substring(8, 24).toUpperCase();
        String hash = base64Encoder.encodeToString(md5Hash.getBytes());

        String urlHash = "";
        try {
            urlHash = URLEncoder.encode(hash, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        params.put("appid", appId);
        params.put("method", method);
        params.put("data", base64QueryParams);
        params.put("nonce", nonce);
        params.put("hash", urlHash);

        return params;
    }

    String encodeByMD5(String encryptStr){
        MessageDigest md5;
        try {
            md5 = MessageDigest.getInstance("MD5");
            byte[] md5Bytes = md5.digest(encryptStr.getBytes());
            StringBuffer hexValue = new StringBuffer();
            for (int i = 0; i < md5Bytes.length; i++) {
                int val = ((int) md5Bytes[i]) & 0xff;
                if (val < 16)
                    hexValue.append("0");
                hexValue.append(Integer.toHexString(val));
            }
            encryptStr = hexValue.toString();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return encryptStr;
    }
}
